/* mainwindow.vala
 *
 * Copyright (C) 2009  fabio "polkqasw" duchi
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author:
 * 	fabio "polkqasw" duchi <fabio.duchi@gmail.com>
 */

using GLib;
using Gtk;
using Notify;

namespace Malem {

public class MainWindow : Gtk.Window {
	private static DBus.Connection conn;
	private Gtk.VBox mainbox;
	private Gee.ArrayList<TaskInterface> list;
	private dynamic DBus.Object interfaceobject;

	private enum JobActions {
		INCONSISTENT=0,
		START=1,
		PAUSE=2,
		SUCCESS=4,
		MANUALLY_ABORT=8,
		FAILURE_ABORT=16,
		CLOSE=32,
		RESTART=64
	}

	
	class TaskInterface:GLib.Object {
		public string dbus_name {get;construct;}
		public string dbus_path {get;construct;}
		private dynamic DBus.Object timeconsumingjob;
		private dynamic DBus.Object job;
		[Widget] public Gtk.Widget main_widget;
		[Widget] private Gtk.Image task_image;
		[Widget] private Gtk.Label task_title;
		[Widget] private Gtk.ProgressBar task_progress;
		[Widget] private Gtk.Button task_start_pause_btn;
		[Widget] private Gtk.Image task_start_pause_image;
		[Widget] private Gtk.Button task_stop;
		[Widget] private Gtk.Label task_description;
		[Widget] private Gtk.Label task_description_no_properties;
		[Widget] private Gtk.Expander task_properties;

		public TaskInterface(string dbus_name, string dbus_path) {
			this.dbus_name = dbus_name;
			this.dbus_path = dbus_path;
		}
		
		construct {
			job = MainWindow.conn.get_object(this.dbus_name, this.dbus_path, "org.gnome.Mathusalem.Job");
			timeconsumingjob = MainWindow.conn.get_object(this.dbus_name, this.dbus_path, "org.gnome.Mathusalem.TimeConsumingJob");
			timeconsumingjob.onProgressChanged += on_task_progress_changed;
			timeconsumingjob.onStatusChanged += on_task_status_changed;
		}
		
		
		
		private void on_task_progress_changed() {
			update_interface();
		}

		private void show_notify(string summary) {
/*			var notify = new Notify.Notification(this.task.get_title()+"</i>"+summary, message, task.get_task_icon_name(), this.main_widget);
			notify.add_action("id0", "fai qualcosa", (Notify.ActionCallback)actioncallback, (void *)this, null);
			notify.add_action("id1", "fai altro", (Notify.ActionCallback)actioncallback, (void *)this, null);
			try{
				notify.show();
			} catch (GLib.Error foo) {
				stderr.printf("Oops %s\n", foo.message);
			}*/
		}

		public static void actioncallback(Notification notify, string actid, TaskInterface *p3) {
//			message("Widget: "+p3->main_widget.get_name());
			message("Action: "+actid);
		}

		private void on_task_status_changed() {
			uint32 action = timeconsumingjob.getStatus();
			switch (action) {
				case JobActions.MANUALLY_ABORT:
					this.show_notify("<b>aborted</b>");
					break;
				case JobActions.CLOSE:
					this.main_widget.destroy();
					this.unref();
					break;
				case JobActions.START:
					this.task_start_pause_image.stock = "gtk-media-pause";
					this.task_start_pause_btn.clicked -= on_click_start_task;
					this.task_start_pause_btn.clicked -= on_click_pause_task;
					this.task_start_pause_btn.clicked += on_click_pause_task;
					this.main_widget.show();
					break;
				case JobActions.PAUSE:
					this.show_notify("<b>on pause</b>");
					this.task_start_pause_image.stock = "gtk-media-play";
					this.task_start_pause_btn.clicked -= on_click_start_task;
					this.task_start_pause_btn.clicked -= on_click_pause_task;
					this.task_start_pause_btn.clicked += on_click_start_task;
					break;
			}
		}

		public void create_all() {
			var builder = new Builder();
			try {
				builder.add_from_file("mathusalem.ui");
			} catch (GLib.Error foo) {
				stderr.printf("Oops %s\n", foo.message);
			}

			this.main_widget = (Gtk.Widget)builder.get_object("mainbox");
			this.main_widget.hide();
			this.main_widget.name = "task"+this.dbus_name+":"+this.dbus_path;
			this.task_image = (Gtk.Image)builder.get_object("task_image");

			this.task_image = (Gtk.Image)builder.get_object("task_image");
			this.task_title = (Gtk.Label)builder.get_object("task_title");
			this.task_progress = (Gtk.ProgressBar)builder.get_object("task_progress");
			this.task_start_pause_btn = (Gtk.Button)builder.get_object("task_start_pause_btn");
			this.task_start_pause_image = (Gtk.Image)builder.get_object("task_start_pause_image");
			this.task_stop = (Gtk.Button)builder.get_object("task_stop");
			this.task_description = (Gtk.Label)builder.get_object("task_description");
			this.task_description_no_properties = (Gtk.Label)builder.get_object("task_description_no_properties");
			this.task_properties = (Gtk.Expander)builder.get_object("task_properties");

			this.task_stop.clicked += on_clicked_stop_task;


			update_interface();
		}

		private void on_click_pause_task(Gtk.Button btn) {
			message("pausa");
			timeconsumingjob.pause();
		}

		private void on_click_start_task(Gtk.Button btn) {
			message("start");
			timeconsumingjob.start();
		}

		private void on_clicked_stop_task(Gtk.Button btn) {
			message("stop");
			timeconsumingjob.stop();
		}

		private void update_interface() {
			string iconname = job.getJobIcon();
			string title = job.getTitle();
			string descr = job.getDescription();
			bool canpause = timeconsumingjob.getCapability((uint32)JobActions.PAUSE);
			bool canabort = timeconsumingjob.getCapability((uint32)JobActions.MANUALLY_ABORT);
			uint32 status = timeconsumingjob.getStatus();
			double progress = timeconsumingjob.getProgress();
			
			if (FileUtils.test(iconname, FileTest.EXISTS))
				this.task_image.set_from_file(iconname);
			else
				this.task_image.set_from_icon_name(iconname, IconSize.LARGE_TOOLBAR);

			this.task_title.label = "<small>"+title+"</small>";
			this.task_progress.fraction = progress/100;
			string pgr_text="";
			uint64 est_time = timeconsumingjob.getEstimatedTimeRemain();
			pgr_text = (est_time%60).to_string()+" sec";
			est_time = est_time/60;
			if (est_time>0) {
				pgr_text = (est_time%60).to_string()+" min "+pgr_text;
				est_time = est_time/60;
			}
			if (est_time>0) {
				pgr_text = (est_time%24).to_string()+" hour "+pgr_text;
				est_time = est_time/24;
			}
			if (est_time>0)
				pgr_text = est_time.to_string()+" day "+pgr_text;
			this.task_progress.text = pgr_text;
			if (canpause) {
				if (status==JobActions.START) {
					this.task_start_pause_image.stock = "gtk-media-pause";
					this.task_start_pause_btn.clicked -= on_click_start_task;
					this.task_start_pause_btn.clicked -= on_click_pause_task;
					this.task_start_pause_btn.clicked += on_click_pause_task;
				} else {
					this.task_start_pause_image.stock = "gtk-media-play";
					this.task_start_pause_btn.clicked -= on_click_start_task;
					this.task_start_pause_btn.clicked -= on_click_pause_task;
					this.task_start_pause_btn.clicked += on_click_start_task;
				}
				this.task_start_pause_btn.show();
			} else {
				this.task_start_pause_btn.hide();
			}
			if(canabort)
				this.task_stop.show();
			else
				this.task_stop.hide();
			this.task_description.label = "<small>"+descr+"</small>";
			this.task_description_no_properties.label = this.task_description.label;
		}


	}

    construct {
		dynamic DBus.Object servicemanager;
		string interface_path;
        this.title = "Mathusalem";
        this.create_widgets ();
		list = new Gee.ArrayList<TaskInterface>();
		

		try {
			MainWindow.conn = DBus.Bus.get(DBus.BusType.SESSION);
		} catch (DBus.Error e) {
			message("problema");
		}

		servicemanager = MainWindow.conn.get_object("org.gnome.Mathusalem", "/org/gnome/Mathusalem/Services", "org.gnome.Mathusalem.ServiceManager");
		interface_path = servicemanager.getInterfaceDBusPath("org.gnome.Mathusalem.TimeConsumingJob");
		stdout.printf("path: %s\n", interface_path);
		interfaceobject = MainWindow.conn.get_object("org.gnome.Mathusalem", interface_path, "org.gnome.Mathusalem.Interface");
		interfaceobject.onAddedJob += added_task;
		interfaceobject.onRemovingJob += removing_task;
		
		/*load current jobs*/
		string[] dbus_urls;
		string[] url;
		uint32 n_jobs;
		
		int i;
		dbus_urls = interfaceobject.getCurrentJobs(out n_jobs);
		i=0;
		while (i<n_jobs) {
			url = dbus_urls[i].split(":");
			this.added_task(interfaceobject, url[0], url[1]);
			i++;
		}
	}

    public void create_widgets () {
        this.destroy += Gtk.main_quit;

		this.mainbox = new VBox(false, 0);
		this.add(this.mainbox);
    }

	private void added_task(dynamic DBus.Object proxy, string dbus_name, string dbus_path) {
		stdout.printf("added task: %s:%s\n", dbus_name, dbus_path);
		var task_interface = new TaskInterface(dbus_name, dbus_path);
		task_interface.create_all();
		list.add(task_interface);

		
		this.mainbox.pack_end(task_interface.main_widget, true, false, 0);
	}
	
	private void removing_task(dynamic DBus.Object proxy, string dbus_name, string dbus_path, bool isCompleted) {
		stdout.printf("removing task: %s:%s [%s]\n", dbus_name, dbus_path, (isCompleted?"complete":"crashed"));
		foreach (TaskInterface t in list) {
			if ((t.dbus_name==dbus_name) && (t.dbus_path==dbus_path)) {
				this.mainbox.remove(t.main_widget);
				list.remove(t);
				break;
			}
		}
	}

    static int main (string[] args) {
        Gtk.init (ref args);

        var mainwin = new MainWindow ();
        mainwin.show_all ();

        Gtk.main ();
        return 0;
    }
}

}
